package zhongbo.javaweb.instagram.util;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

import static zhongbo.javaweb.instagram.util.DateFormatUtil.formatMs;

/**
 * 说明：
 *
 * @author zhongboWork
 * @version 1.0
 * @since 2021-12-16 10:46
 */
@Slf4j
public class PerformanceUtil {

    private static ThreadLocal<Map<Object, Long>> threadLocal = ThreadLocal.withInitial(HashMap::new);

    private static void removeLong(Object key) {
        Map<Object, Long> longMap = threadLocal.get();
        longMap.remove(key);
    }

    private static Long getLong(Object key) {
        Map<Object, Long> longMap = threadLocal.get();
        return longMap.get(key);
    }

    private static void setLong(Object key, Long value) {
        Map<Object, Long> longMap = threadLocal.get();
        longMap.put(key, value);
    }

    /**
     * 统计时间开始
     */
    public static void countStart() {
        Thread key = Thread.currentThread();
        countStart(key);
    }

    /**
     * 统计时间开始
     *
     * @param key 自定义分组key
     */
    public static void countStart(Object key) {
        Long aLong = getLong(key);
        if (aLong != null) {
            Long count = countEnd();
            String countMs = formatMs(count);
            log.warn("key: {}; 统计时间开始, 错误的使用方式:" +
                    " countStart()使用后,须使用count()结束上次统计." +
                    " start: {}, cost: {}", key, aLong, countMs);
        }
        setLong(key, System.currentTimeMillis());
    }

    /**
     * 统计时间结束
     *
     * @return 统计时间
     */
    public static Long countEnd() {
        Thread key = Thread.currentThread();
        return countEnd(key);
    }

    /**
     * 统计时间结束
     *
     * @param key 自定义分组key
     * @return 统计时间
     */
    public static Long countEnd(Object key) {
        return countEnd(key, true);
    }

    /**
     * 统计时间结束
     *
     * @param key        自定义分组key
     * @param removeTime 是否移除统计开始时间
     * @return 统计时间
     */
    private static Long countEnd(Object key, boolean removeTime) {
        long currentTimeMillis = System.currentTimeMillis();
        Long aLong = getLong(key);
        if (aLong == null) {
            log.warn("key: {}, removeTime: {}; 统计时间结束, 错误的使用方式: " +
                    "使用count()前,须使用countStart()记录开始统计时间.", key, removeTime);
            return 0L;
        }
        if (removeTime) {
            removeLong(key);
        }
        long pastMs = currentTimeMillis - aLong;
        if (pastMs < 0) {
            log.warn("key: {}, removeTime: {}; pastMs < 0, pastMs = {}", key, removeTime, pastMs);
        }
        return pastMs;
    }

    /**
     * 统计时间结束的文本格式
     *
     * @return 统计时间 00:00:00:000 或 1D00:00:00:000
     */
    public static String countEndStr() {
        Thread key = Thread.currentThread();
        return formatMs(countEnd(key));
    }

    /**
     * 统计时间结束的文本格式
     *
     * @return 统计时间 00:00:00:000 或 1D00:00:00:000
     */
    public static String countEndStr(Object key) {
        return formatMs(countEnd(key));
    }

    /**
     * 统计时间中间
     * <p>
     * 已过时间, 不会清除开始时间
     *
     * @return 统计中间时间
     */
    public static Long countMiddle() {
        Thread key = Thread.currentThread();
        return countEnd(key, false);
    }

    /**
     * 统计时间中间
     * <p>
     * 已过时间, 不会清除开始时间
     *
     * @param key 自定义分组key
     * @return 统计中间时间
     */
    public static Long countMiddle(Object key) {
        return countEnd(key, false);
    }

    /**
     * 统计时间中间的文本格式
     * <p>
     * 已过时间, 不会清除开始时间
     *
     * @return 统计中间时间 00:00:00:000 或 1D00:00:00:000
     */
    public static String countMiddleStr() {
        return formatMs(countMiddle());
    }

    /**
     * 统计时间中间的文本格式
     * <p>
     * 已过时间, 不会清除开始时间
     *
     * @param key 自定义分组key
     * @return 统计中间时间 00:00:00:000 或 1D00:00:00:000
     */
    public static String countMiddleStr(Object key) {
        return formatMs(countMiddle(key));
    }
}
